package basics;

import java.util.Iterator;

import Jama.Matrix;

public class DenseVector extends Vector implements DenseVectorMatrix {

	Matrix innerMatrix;

	public DenseVector(int n) {
		innerMatrix = new Matrix(1, n);
	}

	public DenseVector(Double[] d) {
		innerMatrix = new Matrix(utils.Converter.toDouble(d), 1);
	}

	public DenseVector(double[] d) {
		innerMatrix = new Matrix(d, 1);
	}

	DenseVector(Matrix newMatix) {
		innerMatrix = newMatix;
	}

	public DenseVector(int length, double val) {
		innerMatrix = new Matrix(length, 1, val);
	}

	public int length() {
		return innerMatrix.getColumnDimension() > innerMatrix.getRowDimension() ? innerMatrix.getColumnDimension()
				: innerMatrix.getRowDimension();
	}

	@Override
	public void set(double v, int... i) {
		if (innerMatrix.getColumnDimension() > innerMatrix.getRowDimension()) {
			innerMatrix.set(0, i[0], v);
		} else {
			innerMatrix.set(i[0], 0, v);
		}
	}

	@Override
	public double get(int... i) {
		if (innerMatrix.getColumnDimension() > innerMatrix.getRowDimension()) {
			return innerMatrix.get(0, i[0]);
		}

		return innerMatrix.get(i[0], 0);
	}

	public double[] values() {
		return innerMatrix.getColumnPackedCopy();
	}

	@Override
	protected Vector newInstance(int n) {
		return new DenseVector(n);
	}

	@Override
	public VectorMatrix transpose() {
		return new DenseVector(innerMatrix.transpose());
	}

	@Override
	public VectorMatrix divide(VectorMatrix a) {
		Vector f = newInstance(length());
		for (int i = 0; i < length(); i++) {
			f.set(get(i) / a.get(i), i);
		}
		return f;
	}

	@Override
	public basics.Matrix times(VectorMatrix m) {
		basics.Matrix v = null;
		if (m instanceof DenseVectorMatrix) {
			v = (basics.Matrix) new DenseMatrix(innerMatrix.times(((DenseVectorMatrix) m).getInnerMatrix()));
		}

		return v;
	}

	@Override
	public basics.Matrix timesEqual(VectorMatrix m) {
		basics.Matrix v = times(m);
		if (v instanceof DenseVectorMatrix) {
			innerMatrix = new Jama.Matrix((((DenseVectorMatrix) v).getInnerMatrix()).getArray());
		}

		return v;
	}

	@Override
	public Matrix getInnerMatrix() {
		return innerMatrix;
	}

	@Override
	public int length(int d) {
		return length();
	}

	@Override
	public Iterator<Double> iterator() {
		return VectorMatrixUtils.getIterator(this);
	}

	@Override
	public int dimesnsion() {
		return 1;
	}

	@Override
	public double max() {
		return VectorMatrixUtils.max(this);
	}

	public String toString() {
		return VectorMatrixUtils.toString(this);
	}

	@Override
	public Vector getColumnVector() {
		if (innerMatrix.getRowDimension() < innerMatrix.getColumnDimension()) {
			return new DenseVector(innerMatrix.transpose());
		}
		return new DenseVector(innerMatrix.copy());
	}

	@Override
	public Vector getRowVector() {
		return new DenseVector(innerMatrix.getRowPackedCopy());
	}

	public static DenseVector getValuedVector(int n, double d) {
		Matrix m = new Matrix(n, 1, d);
		return new DenseVector(m);
	}

	@Override
	public double norm2() {
		return innerMatrix.norm2();
	}
}
